using System;
using System.Text;
using System.Collections.Generic;

namespace AntiXssExperimental {
public class CssEncoder
{
static int Bits(int m, int n, int c){return ((c >> n) & ~(-2 << (m - n)));}

public static string Apply(string input){
var output = new StringBuilder(input.Length >= 16384 ? input.Length : (int)(Math.Min(16384, (long)input.Length * 8)));
int r0 = 0;int state = 0;
for (int i = 0; i < input.Length; i++){
int c = (int)input[i];
switch (state){
case (0): {
  if ((((0x30<=c)&&(Bits(15,6,c)==0)&&(Bits(5,0,c)<=0x39))||((0x41<=c)&&(Bits(15,7,c)==0)&&(Bits(6,0,c)<=0x5A))||((0x61<=c)&&(Bits(15,7,c)==0)&&(Bits(6,0,c)<=0x7A)))) {
    output.Append((char)c);
    r0 = 0;
    state = 0;
  } else {
    if ((Bits(15,8,c)==0)) {
      output.Append((char)0x5C);
      output.Append((char)0x30);
      output.Append((char)0x30);
      output.Append((char)0x30);
      output.Append((char)0x30);
      output.Append((char)(((c>>4)&0xF)+(((c>>4)&0xF)<=9 ? 48 : 55)));
      output.Append((char)((c&0xF)+((c&0xF)<=9 ? 48 : 55)));
      r0 = 0;
      state = 0;
    } else {
      if ((Bits(15,12,c)==0)) {
        output.Append((char)0x5C);
        output.Append((char)0x30);
        output.Append((char)0x30);
        output.Append((char)0x30);
        output.Append((char)(((c>>8)&0xF)+(((c>>8)&0xF)<=9 ? 48 : 55)));
        output.Append((char)(((c>>4)&0xF)+(((c>>4)&0xF)<=9 ? 48 : 55)));
        output.Append((char)((c&0xF)+((c&0xF)<=9 ? 48 : 55)));
        r0 = 0;
        state = 0;
      } else {
        if (((0xD800<=c)&&(c<=0xDBFF))) {
          r0 = c;
          state = 1;
        } else {
          if (((c==0xFFFE)||(c==0xFFFF)||((0xDC00<=c)&&(c<=0xDFFF)))) {
            output.Append((char)0xFFFD);
            r0 = 0;
            state = 0;
          } else {
            output.Append((char)0x5C);
            output.Append((char)0x30);
            output.Append((char)0x30);
            output.Append((char)(((c>>12)&0xF)+(((c>>12)&0xF)<=9 ? 48 : 55)));
            output.Append((char)(((c>>8)&0xF)+(((c>>8)&0xF)<=9 ? 48 : 55)));
            output.Append((char)(((c>>4)&0xF)+(((c>>4)&0xF)<=9 ? 48 : 55)));
            output.Append((char)((c&0xF)+((c&0xF)<=9 ? 48 : 55)));
            r0 = 0;
            state = 0;
          }
        }
      }
    }
  }
break;}
case (1): {
  if (((0xDC00<=c)&&(c<=0xDFFF))) {
    output.Append((char)0x5C);
    output.Append((char)(Bits(9,6,r0)==0xF ? 0x31 : 0x30));
    output.Append((char)(((1+Bits(15,6,r0))&0xF)+(((1+Bits(15,6,r0))&0xF)<=9 ? 48 : 55)));
    output.Append((char)((Bits(15,2,r0)&0xF)+((Bits(15,2,r0)&0xF)<=9 ? 48 : 55)));
    output.Append((char)((((Bits(1,0,r0)<<2)|Bits(9,8,c))&0xF)+((((Bits(1,0,r0)<<2)|Bits(9,8,c))&0xF)<=9 ? 48 : 55)));
    output.Append((char)(((c>>4)&0xF)+(((c>>4)&0xF)<=9 ? 48 : 55)));
    output.Append((char)((c&0xF)+((c&0xF)<=9 ? 48 : 55)));
    r0 = 0;
    state = 0;
  } else {
    if ((((0x30<=c)&&(Bits(15,6,c)==0)&&(Bits(5,0,c)<=0x39))||((0x41<=c)&&(Bits(15,7,c)==0)&&(Bits(6,0,c)<=0x5A))||((0x61<=c)&&(Bits(15,7,c)==0)&&(Bits(6,0,c)<=0x7A)))) {
      output.Append((char)0xFFFD);
      output.Append((char)c);
      r0 = 0;
      state = 0;
    } else {
      if ((Bits(15,8,c)==0)) {
        output.Append((char)0xFFFD);
        output.Append((char)0x5C);
        output.Append((char)0x30);
        output.Append((char)0x30);
        output.Append((char)0x30);
        output.Append((char)0x30);
        output.Append((char)(((c>>4)&0xF)+(((c>>4)&0xF)<=9 ? 48 : 55)));
        output.Append((char)((c&0xF)+((c&0xF)<=9 ? 48 : 55)));
        r0 = 0;
        state = 0;
      } else {
        if ((Bits(15,12,c)==0)) {
          output.Append((char)0xFFFD);
          output.Append((char)0x5C);
          output.Append((char)0x30);
          output.Append((char)0x30);
          output.Append((char)0x30);
          output.Append((char)(((c>>8)&0xF)+(((c>>8)&0xF)<=9 ? 48 : 55)));
          output.Append((char)(((c>>4)&0xF)+(((c>>4)&0xF)<=9 ? 48 : 55)));
          output.Append((char)((c&0xF)+((c&0xF)<=9 ? 48 : 55)));
          r0 = 0;
          state = 0;
        } else {
          if (((0xD800<=c)&&(c<=0xDBFF))) {
            output.Append((char)0xFFFD);
            r0 = c;
            state = 1;
          } else {
            if (((c==0xFFFE)||(c==0xFFFF))) {
              output.Append((char)0xFFFD);
              output.Append((char)0xFFFD);
              r0 = 0;
              state = 0;
            } else {
              output.Append((char)0xFFFD);
              output.Append((char)0x5C);
              output.Append((char)0x30);
              output.Append((char)0x30);
              output.Append((char)(((c>>12)&0xF)+(((c>>12)&0xF)<=9 ? 48 : 55)));
              output.Append((char)(((c>>8)&0xF)+(((c>>8)&0xF)<=9 ? 48 : 55)));
              output.Append((char)(((c>>4)&0xF)+(((c>>4)&0xF)<=9 ? 48 : 55)));
              output.Append((char)((c&0xF)+((c&0xF)<=9 ? 48 : 55)));
              r0 = 0;
              state = 0;
            }
          }
        }
      }
    }
  }
break;}
default: {
  throw new Exception("CssEncoder");
}
}
}
switch (state){
case (0): {
break;}
case (1): {
  output.Append((char)0xFFFD);
break;}
default: {
  throw new Exception("CssEncoder");
}
}
return output.ToString();
}
}
}
